/*
 * Copyright (c) 2011-2012 Alexander Dubu
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * o  Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * o  Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * o  Neither the name Axil nor the names of its contributors may be used to
 *    endorse or promote products derived from this software without specific
 *    prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package axil.stdlib.time.type;

import axil.api.AxilObject;
import axil.api.AxilType;
import axil.framework.type.AbstractType;
import axil.framework.type.NativeEquivalent;

import java.util.Calendar;

import static axil.framework.Functions.leading;


/**
 * Type metadata for the time object. Do NOT create an instance of this
 * class. No good can come from it. Only access to the type metadata from the
 * value class.
 */
class Time_Type extends AbstractType implements NativeEquivalent {
	static final AxilType object = new Time_Type();

	private Time_Type() {
		super("time");
	}


	/**
	 * Get the list of native Java types that this type is equivalent to. The
	 * list returned is never null nor empty.
	 */
	public Class[] natives() {
		return new Class[] {java.sql.Time.class};
	}


	/**
	 * Parse the given text as a representation of the canonical form of this
	 * type. A null is returned if the text does not represent a valid object.
	 * The string given cannot be null. The string is recognized in one of two
	 * forms:
	 * <pre>
	 * 		12-hour time:	3:45pm
	 * 		24-hour time:	15:03
	 * </pre>
	 * If the meridian is not specified, then the value is assumed to be 24-hour
	 * time.
	 */
	public AxilObject parse(String text) {
		if (text.length() > 2) {
			int i = text.indexOf(':');
			if (i > 0) {
				try {
					String hrs = text.substring(0, i);
					int h = 0;
					if (! hrs.equals("0")) {
						h = Integer.parseInt(leading(hrs, '0'));
					}
					char meridian = Character.toUpperCase(
					                    text.charAt(text.length() - 2));
					if ((meridian == 'A') || (meridian == 'P')) {
						int m = Integer.parseInt(
						            text.substring(i + 1, text.length() - 2));
						return new Time(h, m, meridian);
					}
					int m = Integer.parseInt(text.substring(i + 1));
					return new Time(h, m);
				} catch (NumberFormatException e) {
					// IGNORED
				}
			}
		}
		return null;
	}


	/**
	 * Transform the given native object into its equivalent value object. The
	 * object given is never null and is guaranteed to be one of the alias types
	 * indicated by this object's type (as reported by the type() method).
	 * If the object is one of the common types, then that indicator is also
	 * given.
	 */
	public AxilObject transform(Object object) {
		java.sql.Time t = (java.sql.Time)object;
		Calendar cal = Calendar.getInstance();
		cal.setTime(t);
		return new Time(
		           cal.get(Calendar.HOUR_OF_DAY),
		           cal.get(Calendar.MINUTE));
	}
}
